import os
import re
import shutil
import subprocess
import zipfile
from multiprocessing import Process
import check_url_md_main
import _queue
from PyQt6.QtCore import QObject, pyqtSignal, QTimer
from openpyxl import Workbook
import check_url_huawei_main
import check_url_huawei_test_main


# 自定义信号类，用于在主进程中发射信号
class SignalEmitter(QObject):
    message_received = pyqtSignal(str)
    progress_updated = pyqtSignal(int)
    task_completed = pyqtSignal()
    result_opened = pyqtSignal()
    show_range_detection_warning = pyqtSignal()

    def __init__(self, queue):
        super().__init__()
        self.queue = queue
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.check_queue)
        self.timer.start(0)

    def check_queue(self):
        try:
            # 从队列中获取消息（非阻塞）
            message = self.queue.get_nowait()
            if isinstance(message, int):
                self.progress_updated.emit(message)
            elif "<class 'multiprocess_operation.CheckUrlProcessMD'>Process is finished" in message:
                self.message_received.emit(message)
                self.task_completed.emit()
                self.result_opened.emit()
            elif "<class 'multiprocess_operation.CheckUrlProcessHuawei'>Process is finished" in message:
                self.message_received.emit(message)
                self.task_completed.emit()
            elif "<class 'multiprocess_operation.CheckUrlProcessHuaweiTest'>Process is finished" in message:
                self.message_received.emit(message)
                self.task_completed.emit()
            elif '输入的检测范围有误，请确认' in message:
                self.message_received.emit(message)
                self.show_range_detection_warning.emit()
            else:
                self.message_received.emit(message)
        except _queue.Empty:
            pass


class DecompressZipProcess(Process):
    """该进程用于解压耗时操作"""
    def __init__(self, queue, zip_path, dir_path):
        super().__init__()
        self.queue = queue
        self.zip_path = zip_path
        self.dir_path = dir_path

    def run(self):
        if not os.path.exists(self.dir_path):
            os.makedirs(self.dir_path)
        f = zipfile.ZipFile(self.zip_path, 'r')
        for file in f.namelist():
            f.extract(file, self.dir_path)
            self.queue.put(file)
        f.close()
        self.queue.put(f'解压完成，解压后路径：{self.dir_path}')
        self.queue.put(f'{self.__class__}Process is finished')


class CheckUrlProcess(Process):
    """该进程用于检测链接"""
    def __init__(self, queue, markdown_path, script_path):
        super().__init__()
        self.queue = queue
        self.markdown_path = markdown_path
        self.script_path = script_path

    def run(self):
        self.queue.put(f'开始检测链接')
        self.queue.put(f'请等待check_url_args.exe运行完毕')
        process = subprocess.Popen(fr'{self.script_path}\check_url_args.exe {self.markdown_path}',
                                   creationflags=subprocess.CREATE_NEW_CONSOLE)
        process.wait()
        # 将结果复制到chick_result
        src_file = f'{self.markdown_path}/超链接.xlsx'  # 源目录路径
        dest_dir = '/'.join(self.markdown_path.split('/')[:-1])
        dest_file = f'{dest_dir}/result_超链接检查.xlsx'  # 目标目录路
        # 复制目录
        try:
            shutil.copy(src_file, dest_file)
            self.queue.put(f"扫描完成,结果存放于：{dest_file}")
        except FileNotFoundError:
            self.queue.put(f"源文件 {src_file} 未找到")
        except PermissionError:
            self.queue.put(f"没有权限复制文件到 {dest_file}")
        except Exception as e:
            self.queue.put(f"复制文件时发生错误: {e}")
        self.queue.put(f'{self.__class__}Process is finished')


class CheckUrlProcessMD(Process):
    """该进程用于检测MD文件链接"""
    def __init__(self, queue, markdown_path, script_path, test_mode):
        super().__init__()
        self.queue = queue
        self.markdown_path = markdown_path
        self.script_path = script_path
        self.test_mode = test_mode

    def run(self):
        self.queue.put(f'开始检测MD文件链接')
        check_url_md_main.main(self.queue, self.markdown_path, self.test_mode)
        self.queue.put(f'{self.__class__}Process is finished')


class CheckUrlProcessReadme(Process):
    """该进程用于检测README文件链接"""
    def __init__(self, queue, dir_path, script_path, test_mode):
        super().__init__()
        self.queue = queue
        self.dir_path = dir_path
        self.script_path = script_path
        self.test_mode = test_mode

    def run(self):
        self.queue.put(f'开始检测README文件链接')
        check_url_md_main.readme_main(self.queue, self.dir_path, self.test_mode)
        self.queue.put(f'{self.__class__}Process is finished')


class CheckUrlProcessHuawei(Process):
    """该进程用于检测联盟官网链接"""
    def __init__(self, queue, test_mode, language, product):
        super().__init__()
        self.queue = queue
        self.test_mode = test_mode
        self.language = language
        self.product = product
        self.start_url = None
        self.end_url = None

    def run(self):
        self.queue.put(f'开始检测现网链接')
        check_url_huawei_main.main(self.queue, self.test_mode, self.language, self.product, self.start_url, self.end_url)
        self.queue.put(f'{self.__class__}Process is finished')


class CheckUrlProcessHuaweiTest(Process):
    """该进程用于检测联盟测试网链接"""
    def __init__(self, queue, test_mode, language, product, proxies):
        super().__init__()
        self.queue = queue
        self.test_mode = test_mode
        self.language = language
        self.product = product
        self.proxies = proxies

    def run(self):
        self.queue.put(f'开始检测测试网链接')
        check_url_huawei_test_main.main(self.queue, self.test_mode, self.language, self.product, self.proxies)
        self.queue.put(f'{self.__class__}Process is finished')


class GetHyperLinkProcess(Process):
    """该进程用于获取超链接"""
    def __init__(self, queue, to_be_check_path):
        super().__init__()
        self.queue = queue
        self.to_be_check_path = to_be_check_path
        self.title_dic = {}  # 所有topic信息 {topic: path}
        self.hyper_dic = {}  # 所有topic下的链接信息 {topic: {hyper_title: link}}

    def run(self):
        self.queue.put('开始获取超链接')
        self.title_dic = self.get_topic(self.to_be_check_path)
        if len(self.title_dic) == 0:
            self.queue.put(f'{self.__class__}Process is finished')
        else:
            self.get_hyperlink()
            self.write_to_excel()
            # 将结果复制到chick_result
            src_file = f'{self.to_be_check_path}/超链接.xlsx'  # 源目录路径
            dest_dir = '/'.join(self.to_be_check_path.split('/')[:-1])
            dest_file = f'{dest_dir}/result_获取超链接.xlsx'  # 目标目录路
            # 复制目录
            try:
                shutil.copy(src_file, dest_file)
                self.queue.put(f"扫描完成,结果存放于：{dest_file}")
            except FileNotFoundError:
                self.queue.put(f"源文件 {src_file} 未找到")
            except PermissionError:
                self.queue.put(f"没有权限复制文件到 {dest_file}")
            except Exception as e:
                self.queue.put(f"复制文件时发生错误: {e}")
            self.queue.put(f'{self.__class__}Process is finished')

    def get_topic(self, path):
        """
        获取所有topic路径
        :param path: markdown路径
        :return: 所有topic信息 {topic: path}
        """
        md_path = path
        book_map = None
        topic_info = {}
        for file in os.listdir(md_path):
            if '_bookmap_' in file:
                book_map = os.path.join(md_path, file)
                break
        if book_map is not None:
            with (open(book_map, 'r', encoding='utf-8') as f):
                line = f.read()
                pattern = r'\[(?P<title>.*?)\]\((?P<path>.*?\.md)\)'
                i_list = re.finditer(pattern=pattern, string=line)
                for i in i_list:
                    topic_info[i.group('title')] = os.path.join(md_path, i.group('path'))
        else:
            self.queue.put('未找到bookmap文件，请检查')
        return topic_info

    def get_hyperlink(self):
        """
        获取所有topic下的链接信息 {topic: {hyper_title: link}}
        :return:
        """
        for md_path in self.title_dic.values():
            with open(md_path, 'r', encoding='utf-8') as f:
                text = f.read()
                pattern = r'\[(?P<hyper_title>.*?)\]\((?P<link>.*?)\)'
                i_list = re.finditer(pattern=pattern, string=text)
                for i in i_list:
                    if i.group('hyper_title') == '':
                        continue
                    if not i.group('link').startswith('http'):
                        if '.md' not in i.group('link') and '#' not in i.group('link'):
                            continue
                    if i.group('link').startswith('figures') or i.group('link').startswith('public_sys-resources'):
                        continue
                    link = i.group('link')
                    if link.startswith('#'):
                        link = md_path.split("\\")[-1] + link
                    if self.hyper_dic.get(md_path.split("\\")[-1][:-3]):
                        self.hyper_dic[md_path.split("\\")[-1][:-3]].append((i.group('hyper_title'), link))
                    else:
                        self.hyper_dic[md_path.split("\\")[-1][:-3]] = [(i.group('hyper_title'), link)]

    def write_to_excel(self):
        """
        将获取到的hyper信息写入导表格中
        :return:
        """
        wb = Workbook()
        ws = wb.active
        ws.append(['Topic', '链接信息', '链接地址'])

        for key, value in self.hyper_dic.items():
            for v in value:
                ws.append([key, v[0], v[1]])
        wb.save(os.path.join(self.to_be_check_path, '超链接.xlsx'))
